package com.github.llyb120.workflow.entity;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;
import com.github.llyb120.workflow.definition.Node;
import lombok.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static com.github.llyb120.workflow.WorkflowHolder.storageAdapter;

@Data
@NoArgsConstructor
public class FlowData {
    String id;

    String workflowId;

    FlowDealer flowDealer = new FlowDealer();
    List<FlowLog> logs = new ArrayList<>();

    //节点快速查找树
    FlowDataLeaf flowDataLeaf;

    Map<String, Object> attributeMap = new JSONObject();

    FlowDataStatus status;


    /**
     * 查询提交树中的叶子节点
     * 只能提交到最后一级，所以只能查询最后
     *
     * @param leafId
     * @return
     */
    public FlowDataLeaf findDataLeaf(@NonNull String leafId){
        if (flowDataLeaf == null) {
            throw new RuntimeException();
        }
        return flowDataLeaf.lastLevel().stream()
                .filter(e -> e.getId().equals(leafId))
                .findFirst()
                .orElseThrow(() -> new RuntimeException());
    }


    public void addDataLeaf(FlowDataLeaf parent, FlowDataLeaf child){
        if (flowDataLeaf == null) {
            return;
        }
        flowDataLeaf.add(parent, child);
    }

    public void addDataLeaf(FlowDataLeaf child){
        addDataLeaf(null, child);
    }


    @JSONField(serialize = false)
    public boolean isFinished(){
        return status == FlowDataStatus.FINISHED;
    }

    /**
     * 得到当前运行的节点实例
     *
     * @return
     */
    public List<FlowDataLeaf> findCurrentLeaves(){
        if (flowDataLeaf == null) {
            return new ArrayList<>();
        }
        return flowDataLeaf.lastLevel();
    }

    @JSONField(serialize = false)
    private WorkflowWrapper _workflow;

    public WorkflowWrapper findWorkflow(){
        if (_workflow == null) {
            _workflow = storageAdapter.findWorkFlow(workflowId);
        }
        return _workflow;
    }

    /**
     * 得到节点实例所对应的节点模型
     *
     * @param leafId
     * @return
     */
    public Node findLeafNode(String leafId){
        FlowDataLeaf leaf = flowDataLeaf._getLeaf(leafId);
        if (leaf == null) {
            throw new RuntimeException();
        }
        return findWorkflow().findNode(leaf.getNodeId());
    }

}
